package com.morningstar.qs.basic.db.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;

import com.mstar.qs.common.SqlDateConverter;
import com.mstar.qs.common.SqlTimestampConverter;
import com.mstar.qs.common.UtilDateConverter;

public class BeanBase {

	static {
		ConvertUtils
				.register(new UtilDateConverter(null), java.util.Date.class);
		ConvertUtils.register(new SqlDateConverter(null), java.sql.Date.class);
		ConvertUtils.register(new SqlTimestampConverter(null),
				java.sql.Timestamp.class);

	}
	public <V> V convert(Class<V> clasz) {
		
		V o = null;
		try {
			o = clasz.newInstance();
			return convert(clasz, this);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return o;
	}

	public static <T, V> List<V> convert(List<T> orgi, Class<V> clasz) {
		List<V> dest = new ArrayList<V>();
		for (Object o : orgi) {
			try {
				dest.add(BeanBase.convert(clasz, o));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return dest;
	}

	public static <T, V> V convert(Class<V> clasz, T orig) throws InstantiationException, IllegalAccessException, InvocationTargetException {
		V o = null;
		o = (V) clasz.newInstance();
		BeanUtils.copyProperties(o, orig);
		return o;
	}

	public <V> V convert(Class<V> clasz, Set<String> exceptingNames) {
		V o = null;
		try {
			o = clasz.newInstance();
			BeanUtils.copyProperties(o, this);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return o;
	}

	// public String toString(Set<String> exceptedProperties) {
	// StringBuilder sb = new StringBuilder();
	// BeanInfo bi = null;
	// try {
	// bi = Introspector.getBeanInfo(this.getClass());
	// } catch (IntrospectionException e) {
	// e.printStackTrace();
	// }
	// if (bi != null) {
	// PropertyDescriptor[] pds = bi.getPropertyDescriptors();
	// boolean filter = false;
	// for (PropertyDescriptor pd : pds) {
	// String name = pd.getName();
	// if (exceptedProperties != null && exceptedProperties.contains(name)) {
	// filter = true;
	// }
	// if (!filter) {
	// sb.append(pd.getName()).append(":\t").append(pd.getValue(pd.getName()).toString()).append(System.getProperty("line.separator"));
	// }
	// }
	// }
	// return sb.toString();
	// }

	public String toString() {
		String exception[] = null;
		return generatePrintableString(this, null, exception);
	}

	public String generatePrintableString(Object bean, String separator, String[] exceptedProperties) {
		Set<String> properties = null;
		if (exceptedProperties != null && exceptedProperties.length > 0) {
			properties = new HashSet<String>();
			for (String pro : exceptedProperties) {
				properties.add(pro);
			}
		}
		return generatePrintableString(bean, properties, separator);
	}

	@SuppressWarnings("unchecked")
	private static String generatePrintableString(Object bean, Set<String> exceptedProperties, String separator) {
		StringBuilder sb = new StringBuilder();
		Class c = bean.getClass();
		for (; c != null;) {

			Field[] fields = c.getDeclaredFields();

			// sb.append(String.format(fmt,
			// "Class name",bean.getClass().getName())).append(separator);
			// System.out.println(bean.getClass().getName());
			for (Field f : fields) {
				int m=f.getModifiers();
				if(Modifier.isStatic(m)) continue;
				String fieldName = f.getName();
				if (exceptedProperties != null && exceptedProperties.contains(fieldName))
					continue;
				try {
					PropertyDescriptor pd = new PropertyDescriptor(fieldName, bean.getClass());
					Method method = pd.getReadMethod();
					Object value = method.invoke(bean, new Object[0]);
					String str = String.format(fmt, fieldName, (value == null ? "" : value.toString()));
					// System.out.println(str);
					sb.append(str);
					if (separator == null) {
						sb.append(DEFAULT_SEPARATOR);
					} else {
						sb.append(separator);
					}
				} catch (IntrospectionException e) {
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}

			}
			c=c.getSuperclass();
		}

		return sb.toString();
	}

	private static final String fmt = "%20s = %s";
	private static final String DEFAULT_SEPARATOR = ", ";
}
